package com.yuyou.tas.lesson.service.impl;

import com.yuyou.tas.lesson.mapper.LessonMapper;
import com.yuyou.tas.lesson.service.*;
import com.yuyou.tas.lesson.service.comm.OfficeService;
import com.yuyou.tas.lesson.service.comm.OrganLimitService;
import com.yuyou.tas.lesson.service.comm.Subj7SectLimitService;
import com.yuyou.tas.service.api.admin.service.CommJobAPI;
import com.yuyou.tas.service.api.lesson.dto.LessonDetailDTO;
import com.yuyou.tas.service.api.lesson.dto.LessonPageDTO;
import com.yuyou.tas.service.api.lesson.dto.LessonStatisticDTO;
import com.yuyou.tas.service.api.lesson.entity.*;
import com.yuyou.tas.util.bean.LoginRedisObj;
import com.yuyou.tas.util.bean.Pagination;
import com.yuyou.tas.util.bean.ResBoolSimpleInfo;
import com.yuyou.tas.util.bean.ResourceObj;
import com.yuyou.tas.util.enums.CommEnums;
import com.yuyou.tas.util.enums.OrganLimitEnums;
import com.yuyou.tas.util.enums.lesson.LessonClassEnums;
import com.yuyou.tas.util.enums.lesson.LessonEnums;
import com.yuyou.tas.util.exception.BusinessException;
import com.yuyou.tas.util.message.CommMess;
import com.yuyou.tas.util.tool.DefindBeanUtils;
import com.yuyou.tas.util.tool.LogUtil;
import com.yuyou.tas.util.tool.LoginRedisUtil;
import com.yuyou.tas.util.tool.Sequence;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Date;
import java.util.List;

@Service
public class LessonServiceImpl implements ILessonService{

	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());  
	
	@Autowired
	private LessonMapper lessonMapper;
	
	@Autowired
	private Subj7SectLimitService subj7SectLimitService;
	
	@Autowired
	private OrganLimitService organLimitService;
		
	@Autowired
	private IBaseSectionService baseSectionService;
	
	@Autowired
	private IBaseLevelService baseLevelService;
	
	@Autowired
	private IBaseTermService baseTermService;
	@Autowired
	private ICommDataConfigService commDataConfigService;
	
	@Autowired
	private ILessonChapterService lessonChapterService;
	
	@Autowired
	private ILessonMaterialService lessonMaterialService;
	
	@Autowired
	private IBaseChapterService baseChapterService;
	
	@Autowired
	private ILessonClassChapterService lessonClassChapterService;
	
	@Autowired
	private OfficeService officeService;
	
	@Autowired
	private ILessonClassService lessonClassService;

	@Autowired
	private LessonServiceAopImpl lessonServiceAopImpl;
	
	@Autowired
    private CommJobAPI commJobAPI;
		
	@Override
	public int deleteByPrimaryKey(Long id) {
		return lessonMapper.deleteByPrimaryKey(id);
	}

	@Override
	public int insert(Lesson record) {
		record.setId(Sequence.getSequence().nextId());
		record.setCreateTime(new Date());
		record.setIsSycn(0);
		return lessonMapper.insert(record);
	}

	@Override
	public Lesson selectByPrimaryKey(Long id) {
		return lessonMapper.selectByPrimaryKey(id);
	}

	@Override
	public Lesson selectByPKandOrgan(Long id,Long authOrganizationId){
		return lessonMapper.selectByPKandOrgan( id, authOrganizationId);
	}
	
	
	
	@Override
	public int updateByPrimaryKeySelective(Lesson record) {
		return lessonMapper.updateByPrimaryKeySelective(record);
	}

	@Override
	public int findLessonCount(Pagination<LessonPageDTO> queryPgn) {
		return lessonMapper.findLessonCount(queryPgn);
	}

	@Override
	public List<LessonPageDTO> findLessonPageList(Pagination<LessonPageDTO> queryPgn) {
		return lessonMapper.findLessonPageList(queryPgn);
	}

	@Override
	@Transactional(rollbackFor=Exception.class,timeout=60)
	public ResBoolSimpleInfo<LessonDetailDTO> addOrUpLesson(Lesson record,Long userId) throws Exception {	
		LoginRedisObj obj=LoginRedisUtil.getUserObj(userId);
		subj7SectLimitService.checkByUserId(userId, record.getDataSubject(), record.getBaseSectionId());

		if(record.getId()!=null){
			checkPublicLesson(record.getId());			
			organLimitService.checkOrganByOrganId(obj.getOrganizationId(), record.getId(), OrganLimitEnums.type.lesson);
			//科目，年级不能修改
			record.setpId(null);
			record.setDataSubject(null);		
			record.setBaseSectionId(null);
			this.updateByPrimaryKeySelective(record);
		}else{				
			if(record.getpId()!=null){								
				//引用用已有课程，复制讲次，素材			
				fromLesson(record.getpId(),record,obj);
			}else{
				record.setIsStan(obj.getIsSystem()?1:0);
		    	record.setType(obj.getIsSystem()?CommEnums.standtype.standard.getValue():CommEnums.standtype.defind.getValue());  
				record.setAuthOrganizationId(obj.getOrganizationId());
				record.setCreateUser(obj.getUserId());
				record.setStatus(LessonEnums.status.init.getValue());
				this.insert(record);
			}			
		}	
		Lesson lesson=this.selectByPrimaryKey(record.getId());
		LessonDetailDTO lessonDetailDTO=new LessonDetailDTO();
		DefindBeanUtils.copyProperties(lesson, lessonDetailDTO);
		return new ResBoolSimpleInfo<LessonDetailDTO>(true,null,lessonDetailDTO);
	}

	@Transactional(rollbackFor=Exception.class,timeout=60)
	public void fromLesson(Long pId,Lesson record,LoginRedisObj obj) throws Exception{
		Lesson pLesson=this.selectByPrimaryKey(pId);
		//只能引用本机构或者标准的课程
		if(pLesson.getIsStan().equals(0) && !pLesson.getAuthOrganizationId().equals(obj.getOrganizationId())){
			throw new BusinessException(CommMess.ERR_POWER);
		}
		
		//引用课程科目必须一致
		if(!record.getDataSubject().equals(pLesson.getDataSubject())){
			throw new BusinessException("所选课程科目与现有课程的科目不一致");
		}
		
		subj7SectLimitService.checkByUserId(obj.getUserId(), pLesson.getDataSubject(), pLesson.getBaseSectionId());
		
		//非标准课程引用需要pid
		if(obj.getIsSystem()){
			record.setpId(null);	
		}else{
			record.setpId(pId);	
		}
		record.setIsStan(obj.getIsSystem()?1:0);
    	record.setType(obj.getIsSystem()?CommEnums.standtype.standard.getValue():CommEnums.standtype.defind.getValue());  
		record.setAuthOrganizationId(obj.getOrganizationId());
		record.setCreateUser(obj.getUserId());
		record.setStatus(LessonEnums.status.init.getValue());
		this.insert(record);
		
		//课程讲次
		lessonChapterService.copyChapterByChapter(pId,record,obj);		
		//课程素材
		lessonMaterialService.copylessonMaterial(pId, record);
	}
	
	@Override
	@Transactional(rollbackFor=Exception.class)
	public ResBoolSimpleInfo<String> copyClassLesson(boolean publish,Long lessonClassId,Long pId,Long userId,ResourceObj resourceObj) throws Exception{
		Lesson pLesson=this.selectByPrimaryKey(pId);

		this.validate(true,pId,Collections.emptyList(),Collections.emptyList(),userId);
		if(publish){
			if(!pLesson.getStatus().equals(LessonEnums.status.pass.getValue())){
				throw new BusinessException("未发布的课程不可被引用");
			}			
		}			
		List<LessonChapter> lcList=lessonChapterService.findLessonChapterByLessId(pId);
				
		for(LessonChapter lc:lcList){
			LessonClassChapter lcc=new LessonClassChapter();
			lcc.setLessonId(pId);
			lcc.setLessonChapterId(lc.getId());
			lcc.setLessonClassId(lessonClassId);				
			lessonClassChapterService.insert(lcc);
		}				
		return ResBoolSimpleInfo.getSuccessInfo();
	}
			


	
	@Override
	@Transactional(rollbackFor=Exception.class,timeout=60)
	public ResBoolSimpleInfo<String> syncLessons(List<Lesson> list) throws Exception {	
		
		ResBoolSimpleInfo<String> res=new ResBoolSimpleInfo<String>();
		StringBuilder sb=new StringBuilder();
		for(Lesson l:list){
			try{
				lessonServiceAopImpl.syncLesson(l);
			}catch(Exception e){
				LogUtil.error(logger, "同步课程失败:", e);
				sb.append("同步课程失败:"+e.getMessage()+"|");
			}
		}	
		res.setSuccess(StringUtils.isEmpty(sb.toString()));
		res.setMessage(sb.toString());
		
		return res;
	}



	@Override
	@Transactional(rollbackFor=Exception.class)
	public ResBoolSimpleInfo<String> publishLesson(Long id, int status,
			Long authOrganizationId,Long userId) throws Exception {			
		Lesson lesson=this.selectByPrimaryKey(id);
		if(lesson.getStatus().equals(LessonEnums.status.pass.getValue())||lesson.getStatus().equals(LessonEnums.status.passing.getValue())){
			throw new BusinessException("不能重复发布");
		}
		
		List<LessonChapter> cpList=lessonChapterService.findLessonChapterByLessId(id);
		if(cpList.size()==0){
			throw new BusinessException("课程发布，讲数不能为空");
		}
		if(cpList.size()!=lesson.getChapterNum().intValue()){
			throw new BusinessException("实际讲数与设置不一致，请检查后发布");
		}
		
		subj7SectLimitService.checkByUserId(userId, lesson.getDataSubject(), lesson.getBaseSectionId());
		organLimitService.checkOrganByOrganId(authOrganizationId, id, OrganLimitEnums.type.lesson);
		ResBoolSimpleInfo<String> res=new ResBoolSimpleInfo<>();

		upGradeClassByLesson( lesson.getId(),lesson.getoId(),authOrganizationId);
				
		res.setSuccess(true);
		res.setData(String.valueOf(id));
		return res;
	}

	@Override
	@Transactional(rollbackFor=Exception.class)
	public ResBoolSimpleInfo<String> upGradeClassByLesson(Long lessonId,Long lessonOId,Long authOrganizationId) throws Exception {
		//同步班级课程信息
		List<LessonClass> classList=lessonClassService.findByLessonId(lessonId);
		for(LessonClass lc:classList){
			if(lc.getIsSycn().equals(0)){
				lessonClassService.upGradeClass(lc.getId(), authOrganizationId); 
			}
   
		}
		Lesson upLesson=new Lesson();
		upLesson.setId(lessonId);
		upLesson.setStatus(LessonEnums.status.pass.getValue());
		this.updateByPrimaryKeySelective(upLesson);
		
		return ResBoolSimpleInfo.getSuccessInfo();
	}

	@Override
	public Lesson selectByClassId(Long classId) {
		return lessonMapper.selectByClassId(classId);
	}


	@Override
	@Deprecated
	public ResBoolSimpleInfo<String> delByOrgan7OId(Long oId,
			Long authOrganizationId) {
//		lessonMapper.delLessonByOId(oId, authOrganizationId);
		return ResBoolSimpleInfo.getSuccessInfo();
	}

	@Override
	@Transactional(rollbackFor=Exception.class,timeout=60)
	public ResBoolSimpleInfo<String> delByOrgan7OIds(List<Long> oIds,
			Long authOrganizationId) {
		for(Long oId:oIds){
			this.delByOrgan7OId(oId, authOrganizationId);
		}
		return ResBoolSimpleInfo.getSuccessInfo();
	}

	@Override
	public Lesson selectByOrgan7OId(Long oId, Long authOrganizationId) {
		return lessonMapper.selectByOrgan7OId(oId, authOrganizationId);
	}

	@Override
	public ResBoolSimpleInfo<LessonDetailDTO> detailLesson(Long id,
			Long authOrganizationId,Long userId) throws Exception {
		Lesson lesson=this.selectByPrimaryKey(id);
		subj7SectLimitService.checkByUserId(userId, lesson.getDataSubject(), lesson.getBaseSectionId());
		//只能引用本机构或者标准的课程
		if(lesson.getIsStan().equals(0) && !lesson.getAuthOrganizationId().equals(authOrganizationId)){
			throw new BusinessException(CommMess.ERR_POWER);
		}
		LessonDetailDTO lessonDetailDTO=new LessonDetailDTO();
		DefindBeanUtils.copyProperties(lesson, lessonDetailDTO);
		return new ResBoolSimpleInfo(true,null,lessonDetailDTO);
	}

	@Override
	public void checkPublicLesson(Long lessonId) {
		Lesson l=this.selectByPrimaryKey(lessonId);
		if(l.getStatus().equals(LessonEnums.status.pass.getValue())){
			throw new BusinessException("课程已经发布，不能修改");
		}
	}

	@Override
	public void checkPublicLesson(Lesson l){
		if(l.getStatus().equals(LessonEnums.status.pass.getValue())){
			throw new BusinessException("课程已经发布，不能修改");
		}
	}
	
	/**
	 * 课程和课程讲次权限校验
	 * @param lessonId
	 * @param checkLesson
	 * @param userId
	 * @throws Exception
	 */
	@Override
	public void validate(boolean checkLesson,Long lessonId,List<Long> lessonChapterIds,List<Long> baseChapterIds,Long userId) throws Exception{
		if(userId==null){
			return;
		}
		LoginRedisObj obj=LoginRedisUtil.getUserObj(userId);
				
		//课程
		Lesson l=this.selectByPrimaryKey(lessonId);
		if(checkLesson){
			//非标准引用标准不需要
			if(l.getIsStan().equals(0)){
				organLimitService.checkOrganByOrganId(obj.getOrganizationId(), l.getId(), OrganLimitEnums.type.lesson);				
			}
			subj7SectLimitService.checkByUserId(userId, l.getDataSubject(), l.getBaseSectionId());
		}
		
		//讲次
		for(Long lessonChapterId:lessonChapterIds){
						
			//课程，讲次科目约束
			LessonChapter lessonChapter=lessonChapterService.selectByPrimaryKey(lessonChapterId);
			BaseChapter baseChapter=baseChapterService.selectByPrimaryKey(lessonChapter.getBaseChapterId());
			if(!l.getDataSubject().equals(baseChapter.getDataSubject())){
				throw new Exception("讲次科目与课程不一致");
			}
			
			organLimitService.checkOrganByOrganId(obj.getOrganizationId(), lessonChapter.getId(), OrganLimitEnums.type.lesson_chapter);
			subj7SectLimitService.checkByUserId(userId, baseChapter.getDataSubject(), baseChapter.getBaseSectionId());			
		}
	
		//讲次库
		for(Long baseChapterId:baseChapterIds){
			
			//课程，讲次科目约束
			BaseChapter baseChapter=baseChapterService.selectByPrimaryKey(baseChapterId);
			if(!l.getDataSubject().equals(baseChapter.getDataSubject())){
				throw new BusinessException("讲次:"+baseChapter.getName()+"的科目与课程不一致");
			}			
			BaseChapter b= baseChapterService.selectByPrimaryKey(baseChapterId);
			//课程讲次挑选讲次库不需要机构权限教研，只查不改
//			organLimitService.checkOrganByOrganId(obj.getOrganizationId(), b.getId(), OrganLimitEnums.type.base_chapter);
			subj7SectLimitService.checkByUserId(userId, b.getDataSubject(), b.getBaseSectionId());			
		}
		
	}

	@Override
	public List<Lesson> findPubLessonByOrganId(Long authOrganizationId) {
		return lessonMapper.findPubLessonByOrganId(authOrganizationId);
	}

	@Override
	public int findLessonStatisticCount(Pagination<LessonStatisticDTO> queryPgn) {
		return lessonMapper.findLessonStatisticCount(queryPgn);
	}

	@Override
	public List<LessonStatisticDTO> findLessonStatisticPageList(Pagination<LessonStatisticDTO> queryPgn) {
		List<LessonStatisticDTO> lessonStatisticPageList = lessonMapper.findLessonStatisticPageList(queryPgn);
		for(LessonStatisticDTO lessonStatisticDTO : lessonStatisticPageList){
			lessonStatisticDTO.setCurrentClass(lessonClassService.countLessonClassByLessonIdTrimesterIdStatus(lessonStatisticDTO.getLessonId(), lessonStatisticDTO.getBaseTrimesterId(),
					LessonClassEnums.status.opening.getValue()));
			lessonStatisticDTO.setHistoricClass(lessonClassService.countLessonClassByLessonIdTrimesterIdStatus(lessonStatisticDTO.getLessonId(), lessonStatisticDTO.getBaseTrimesterId(),
					LessonClassEnums.status.end.getValue()));
		}
		return lessonStatisticPageList;
	}

	@Override
	@Transactional(rollbackFor=Exception.class)
	public ResBoolSimpleInfo<String> delLesson(Long id , boolean isSystem) {
		ResBoolSimpleInfo<String> res=new ResBoolSimpleInfo<>();
		if(isSystem){
			List<String> list = lessonClassService.findOrgUseByLess(id);
			if(list != null && list.size() > 0){
				throw new BusinessException("该课程已被"+list.get(0)+"等"+list.size()+"个机构所引用，请先解除关系，再删除");
			}
		}else{
			List<String> list = lessonClassService.findClassNameByLess(id);
			if(list != null && list.size() > 0){
				throw new BusinessException("该课程已被"+list.get(0)+"等"+list.size()+"个班级所引用，请先解除关系，再删除");
			}
		}
		lessonChapterService.delByless(id);//解除讲次关系
		lessonMaterialService.delByless(id);//解除素材关系
		deleteByPrimaryKey(id);//删除客课程
		res.setSuccess(true);
		res.setMessage("删除成功");
		return res;
	}

	@Override
	@Transactional(rollbackFor=Exception.class)
	public ResBoolSimpleInfo<String> cancelPublicLesson(Long organizationId,Long id) throws Exception {

	    organLimitService.checkOrganByOrganId(organizationId, id, OrganLimitEnums.type.lesson);
	    
		ResBoolSimpleInfo<String> res=new ResBoolSimpleInfo<>();
		Lesson updateLes=this.selectByPrimaryKey(id);	
		
		if(updateLes.getStatus()==LessonEnums.status.init.getValue()){
			throw new BusinessException("该课程未发布");
		}
		
		//更改课程发布状态
		Lesson l=new Lesson();
		l.setId(updateLes.getId());
		l.setStatus(LessonEnums.status.init.getValue());
		this.updateByPrimaryKeySelective(l);
		
		//更改改班级的课程同步状态		
		List<LessonClass>lcList=lessonClassService.findByLessonId(updateLes.getId());
		for(LessonClass lc:lcList){
			LessonClass upLc=new LessonClass();
			upLc.setId(lc.getId());
			upLc.setIsSycn(0);
			lessonClassService.updateByPrimaryKeySelective(upLc);	
			//删除班级讲次相关内容
			lessonClassService.delLesCha(lc.getId());			
		}
			
		res.setSuccess(true);
		res.setMessage("取消成功");
		return res;
		
	}
}